package org.yang.plugins.resource.config;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.server.resource.web.server.authentication.ServerBearerTokenAuthenticationConverter;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.authentication.AuthenticationWebFilter;
import org.springframework.security.web.server.authorization.AuthorizationContext;
import org.yang.plugins.resource.handler.RequestAccessDeniedHandler;
import org.yang.plugins.resource.handler.RequestAuthenticationEntryPoint;

import java.util.List;

/**
 * 客户端配置
 *
 * @author haoxr
 * @since 2022/8/28
 */
@Slf4j
@EnableWebFluxSecurity
@Configuration(proxyBeanMethods = false)
@ConfigurationProperties(prefix = "security")
@RequiredArgsConstructor
public class SecurityConfig {

    /**
     * token校验管理器
     */
    private final ReactiveAuthenticationManager tokenAuthenticationManager;
    /**
     * JWT的鉴权管理器
     */
    private final ReactiveAuthorizationManager<AuthorizationContext> accessManager;

    private final RequestAccessDeniedHandler requestAccessDeniedHandler;
    private final RequestAuthenticationEntryPoint requestAuthenticationEntryPoint;


    /**
     * 黑名单请求路径列表
     */
    @Setter
    private List<String> blackPaths;

    @Setter
    private List<String> whitePaths;

    @Bean
    public SecurityWebFilterChain securityFilterChain(ServerHttpSecurity http) {
        AuthenticationWebFilter authenticationWebFilter = new AuthenticationWebFilter(tokenAuthenticationManager);
        authenticationWebFilter.setServerAuthenticationConverter(new ServerBearerTokenAuthenticationConverter());

        http
                .authorizeExchange(exchange ->
                        {
                            if (CollectionUtil.isNotEmpty(blackPaths)) {
                                exchange.pathMatchers(Convert.toStrArray(blackPaths)).authenticated();
                            }
                            if(CollectionUtil.isNotEmpty(whitePaths)) {
                                exchange.pathMatchers(Convert.toStrArray(whitePaths)).permitAll();
                            }
                            //其他的请求必须鉴权，使用鉴权管理器
                            exchange.anyExchange().access(accessManager);
                        }
                )
                .csrf(ServerHttpSecurity.CsrfSpec::disable)
                .addFilterAt(authenticationWebFilter, SecurityWebFiltersOrder.AUTHENTICATION)
            ;
//            http.oauth2ResourceServer(resourceServerConfigurer ->
//                resourceServerConfigurer
//                        .jwt(Customizer.withDefaults())
//                        .authenticationEntryPoint(requestAuthenticationEntryPoint)
//                        .accessDeniedHandler(requestAccessDeniedHandler)
//        );

        //todo 可以改为动态黑/白名单拦截
        log.info("放行路径列表:{},黑名单路径列表:{}", JSONUtil.toJsonStr(whitePaths),JSONUtil.toJsonStr(blackPaths));
        return http.build();
    }



}